#include <head.h>

#define SIZE_BUF_MAX 1024 // 缓冲区大小

// 拷贝任务参数结构体
typedef struct Copy_Args {
    int fd_src;   // 源文件描述符
    int fd_dest;  // 目标文件描述符
    off_t start;  // 拷贝起始位置
    off_t end;    // 拷贝结束位置
} Copy_Args;

// 拷贝文件函数
void* copy_file(void *arg) 
{
    Copy_Args* args = (Copy_Args*)arg; // 获取拷贝任务参数

    // 设定缓冲区
    char buf[SIZE_BUF_MAX];

    // 设定文件起始位置
    lseek(args->fd_src, args->start, SEEK_SET);
    lseek(args->fd_dest, args->start, SEEK_SET);

    // 开始拷贝
    size_t byte_read = 0;  // 每次读取的字节数
    size_t byte_write = 0; // 每次写入的字节数

    while (args->start < args->end) 
    { 
        // 循环拷贝直到结束位置
        if ((byte_read = read(args->fd_src, buf, SIZE_BUF_MAX)) <= 0) 
        { 
            // 读取数据
            break;
        }
        if ((byte_write = write(args->fd_dest, buf, byte_read)) <= 0) 
        { 
            // 写入数据
            break;
        }

        // 更新拷贝位置
        args->start += byte_write;
    }

    return NULL; // 线程退出
}

int main(int argc, char const *argv[]) 
{
    // 检查命令行参数
    if (3 != argc) 
    {
        printf("格式错误 %s dest src\n", argv[0]);
        return 0;
    }

    // 打开文件
    int desk_fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0664); // 目标文件
    OPEN_ERR(desk_fd);

    int src_fd = open(argv[2], O_RDONLY); // 源文件
    OPEN_ERR(src_fd);

    Copy_Args Args;
    Args.fd_src = src_fd;
    Args.fd_dest = desk_fd;

    // 获取文件状态
    struct stat file_stat;
    if (fstat(src_fd, &file_stat) < 0) 
    {
        perror("fstat err");
        close(desk_fd);
        close(src_fd);
        return 0;
    }

    off_t file_size = file_stat.st_size; // 获取文件大小
    int num = 4;                 // 设置线程数量
    off_t part_size = file_size / num; // 计算每个线程拷贝的部分大小
    pthread_t Tid[num];          // 创建多个线程
    Copy_Args Tid_Args[num];     // 多个线程的拷贝任务参数

    // 创建并启动多个线程
    for (size_t i = 0; i < num; i++) 
    {
        Tid_Args[i].fd_src = Args.fd_src;
        Tid_Args[i].fd_dest = Args.fd_dest;
        Tid_Args[i].start = i * part_size;
        Tid_Args[i].end = (i == num - 1) ? file_size : part_size + Tid_Args[i].start;

        if (0 != pthread_create(&Tid[i], NULL, copy_file, (void *)&Tid_Args[i])) 
        {
            printf("pthread_create error\n");
            return 0;
        }
    }

    // 等待多个线程结束
    for (size_t i = 0; i < num; i++) 
    {
        pthread_join(Tid[i], NULL);
    }
    
    printf("文件拷贝成功\n");

    return 0;
}
